﻿// --------------------------------
// <copyright file="PropertyForm.cs" company="Faculty of Information Technology, Czech Technical University in Prague">
//     This document is shared by Microsoft Public License (MS-PL)
//     For further details please see http://msdn.microsoft.com/en-us/library/ff648068.aspx or license.txt.
// </copyright>
// <author>Lukáš Molnár</author>

// <email>molnaluk@fit.cvut.cz</email>

// <date>13. 11. 2011 19:39:37</date>

// <summary>
//
// </summary>
// --------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using FITClub.Episode1.Levels;
using FITClub.TextureMenu;
using FITClub.Util;
using Microsoft.Xna.Framework;

using tm = FITClub.TextureMenu;
using xna = Microsoft.Xna.Framework;

namespace FITClub.LevelBuilder
{
    public partial class PropertyForm : Form
    {
        DefaultsForm defaults;
        LevelBuilderControl builder;
        private Level level;

        public string ConfigTitle
        {
            set { this.groupBox1.Text = string.Format("{0} Config", value); }
        }

        struct DetailItem
        {
            public string DisplayText;
            public IList DataSource;

            public DetailItem(IList source, string name)
            {
                DisplayText = name;
                DataSource = source;
            }

            public override string ToString()
            {
                return this.DisplayText;
            }
        }

        public PropertyForm(DefaultsForm defaults, LevelBuilderControl builder)
        {
            this.defaults = defaults;
            this.builder = builder;
            this.builder.DrawTargetChanged += new System.Action<LevelBuilderControl, LBCDrawTarget>(builder_DrawTargetChanged);
            InitializeComponent();
        }

        private void builder_DrawTargetChanged(LevelBuilderControl lbc, LBCDrawTarget drawTarget)
        {
            switch (drawTarget)
            {
                case LBCDrawTarget.Level:
                    this.ActualLevel = lbc.ActualLevel;
                    this.groupBox1.Text = "Level Config";
                    break;

                case LBCDrawTarget.Menu:
                    this.CustomMenu = lbc.CustomMenu;
                    this.groupBox1.Text = "Menu Config";
                    break;

                case LBCDrawTarget.MenuManager:
                    this.SetSource(tm.MenuManager.Current);
                    this.groupBox1.Text = "Menu Manager Config";
                    break;
                default:
                    SetSource(null);
                    break;
            }
        }

        public Level ActualLevel
        {
            get { return level; }
            set
            {
                level = value;
                if (level != null)
                {
                    this.SetSource(level.Config);
                }
                else
                {
                    this.SetSource(null);
                }
            }
        }

        private void AddedResponse(Type type)
        {
            if (level != null && type == typeof(List<PlatformConfig>))
            {
                builder.AddPlatform(new PlatformConfig()
                {
                    Transforms = defaults.Platform.Transforms,
                    ModelPath = defaults.Platform.ModelPath,
                    Height = defaults.Platform.Height,
                    Width = defaults.Platform.Width
                });
                return;
            }

            this.listPropertyGrid1.InvalidateDataSource();
        }

        private void RemovedResponse(Type type, IList removed)
        {
            if (level != null)
            {
                if (type == typeof(List<PlatformConfig>))
                {
                    foreach (PlatformConfig item in removed)
                    {
                        builder.RemovePlatform(item);
                    }
                }

                if (type == typeof(List<PowerUpConfig>))
                {
                    foreach (PowerUpConfig item in removed)
                    {
                        level.Config.PowerUpConfigs.Remove(item);
                    }
                }

                if (type == typeof(List<Vector2>))
                {
                    foreach (Vector2 item in removed)
                    {
                        level.Config.Respawns.Remove(item);
                    }
                }
            }

            if (customMenu != null)
            {
                if (type == typeof(List<TextureMenu.AMenuItem>))
                {
                    foreach (TextureMenu.AMenuItem item in removed)
                    {
                        customMenu.MenuItems.Remove(item);
                    }
                }

                if (type == typeof(List<TextureMenu.ADisplayable>))
                {
                    foreach (TextureMenu.ADisplayable item in removed)
                    {
                        customMenu.InactiveItems.Remove(item);
                    }
                }
            }

            this.listPropertyGrid1.InvalidateDataSource();
        }

        internal void SetSource(object main)
        {
            if (main != null)
            {
                this.propertyGrid1.SelectedObject = main;
                List<DetailItem> properties = new List<DetailItem>();
                foreach (var p in main.GetType().GetProperties())
                {
                    try
                    {
                        object itm = p.GetValue(main, null);
                        if (itm is IList)
                        {
                            properties.Add(new DetailItem((IList)itm, p.Name));
                        }
                    }
                    catch
                    {
                    }
                }
                this.comboBox1.DataSource = properties;
                if (properties.Count > 0)
                {
                    this.comboBox1.SelectedIndex = 0;
                }
            }
            else
            {
                this.listPropertyGrid1.DataSource = null;
                this.propertyGrid1.SelectedObject = null;
                this.groupBox1.Text = string.Empty;
            }
        }

        private TextureMenu.Menu customMenu;

        public TextureMenu.Menu CustomMenu
        {
            get { return customMenu; }
            set
            {
                customMenu = value;

                SetSource(customMenu);
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.listPropertyGrid1.DataSource = ((DetailItem)comboBox1.SelectedValue).DataSource;
        }

        private void PropertyForm_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Escape)
            {
                this.Hide();
            }
        }

        private void listPropertyGrid1_SelectionChanged(ListPropertyGrid list)
        {
            ResetHighlightBorders();
        }

        public void ResetHighlightBorders()
        {
            this.builder.HighlightBorders.Clear();
            try
            {
                foreach (ADisplayable item in this.listPropertyGrid1.SelectedItems)
                {
                    this.builder.HighlightBorders.Add(item.Bounds);
                }
            }
            catch (Exception exc)
            {
                try
                {
                    foreach (ITransformable item in this.listPropertyGrid1.SelectedItems)
                    {
                        xna.Vector2 v = builder.Game.WorldToScreenPosition(item.Transforms.Translation);
                        this.builder.HighlightBorders.Add(new xna.Rectangle((int)Math.Round(v.X),
                            (int)Math.Round(v.Y), (int)Math.Round(10 * item.Transforms.Scale.X), (int)Math.Round(10 * item.Transforms.Scale.Y)));
                    }
                }
                catch (Exception exc1)
                {
                }
            }
            this.builder.Invalidate();
        }

        internal void MoveSelection(System.Drawing.Point delta)
        {
            try
            {
                foreach (ADisplayable item in this.listPropertyGrid1.SelectedItems)
                {
                    item.Move(new xna.Point(delta.X, delta.Y));
                    IUpdateableItem updatable = item as IUpdateableItem;
                    if (updatable != null)
                    {
                        updatable.Update(new xna.GameTime());
                    }
                }
            }
            catch (Exception exc)
            {
            }
            this.builder.Invalidate();
        }
    }
}